feat(ai-accounts): sort accounts by remaining quota - #929
Merged
Conversation
The AI accounts list could only be ordered by name. With many accounts, finding one that still has headroom meant reading every card. Adds a sort control to the toolbar: by name (default), least quota left first, most quota left first. An account's position is decided by the tightest quota its card actually shows. Scoping it to the visible slots matters: antigravity reports both a 5h and a weekly bucket but the card renders only the 5h one, and ranking by a number the operator cannot see reads as a broken sort. Sorting pulls the full status snapshot once. The list loads status only for the accounts on the current page β correct for rendering, useless for ordering, since sorting a page by numbers only that page has just shuffles it. The endpoint already returns every account when no auth_index filter is given, so no backend change was needed. The order is applied before the slice into pages. Accounts with no reading sort last in both directions and keep name order among themselves. Unknown is not empty and not full; floating it to the top of either direction would bury what the operator opened the view to find. A failed snapshot leaves everything unranked, which preserves name order rather than presenting a partial order as authoritative. The preference and the fetch state are module-scoped and the preference is persisted. AuthFilesPage.tsx and AuthFilesFilesTab.tsx are both frozen at their size baselines, so threading this through as props was not available; the list and the toolbar control read the shared value independently. Neither file is touched by this change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Matches the column-count control it sits beside β same affordance for the same kind of choice, and no second popover implementation on a toolbar that already has one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
kittors
force-pushed
the
feat/ai-accounts-quota-sort
branch
from
August 19, 2026 15:28
30b51f6 to
430535d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The AI accounts list (
/access/ai-accounts) could only be ordered by name. With many accounts, finding one that still has headroom meant reading every card.Adds a sort control to the toolbar: by name (default), least quota left first, most quota left first.
Design decisions worth reviewing
Ranked by the tightest quota the card actually shows. Scoping to the visible slots matters: antigravity reports both a 5h and a weekly bucket but the card renders only the 5h one. Ranking by a number the operator cannot see on the card reads as a broken sort. The rank therefore runs through
resolveQuotaCardSlotsβ the same function that decides what the card displays.Sorting pulls the full status snapshot once. This is the part that made a backend change look necessary, and then turned out not to need one:
The list loads status only for the accounts on the current page (
visibleStatusScopeKey). That is right for rendering and useless for ordering β sorting a page by numbers only that page has just shuffles it. ButGET /ai-accounts/statusalready returns every account when noauth_indexfilter is supplied, so the data was one parameterless call away. The order is applied infilteredFiles, before the slice into pages.Nothing is fetched while sorting by name, so the default view is unaffected.
Unknown sorts last in both directions, keeping name order among themselves. Unknown is not empty and not full; floating it to the top of either direction would bury exactly what the operator opened the view to find. A failed snapshot leaves everything unranked, preserving name order rather than presenting a partial order as authoritative.
Preference and fetch state are module-scoped.
AuthFilesPage.tsx(1210) andAuthFilesFilesTab.tsx(2579) are both frozen at their size baselines, and the gate only permits shrinking β threading this through as props was not available. The list and the toolbar control read the shared value independently. Neither file is touched by this change. The control lives inAuthFilesToolbarActions.tsx, which was itself extracted to keep the tab under the ratchet.The control shows a spinner while the snapshot loads; without it the button looks inert for the duration of the request, which reads as broken.
No backend change
GET /ai-accounts/statuswith no filter already returns every account with its quota windows (ListStatustreats an empty filter as "all"). Verified ininternal/management/aiaccountstatus/service.go.Testing
7 new tests covering the rank calculation β including that antigravity's hidden weekly window is not used β and the shared preference (default, cross-instance sharing, persistence, unrecognised stored value).
tsc,oxlint, and all four structure gates pass. Fullpages/auth-filessuite green at 236 tests.Not verified in a browser
I started the dev server and stopped at the login screen β I don't enter credentials. The control's appearance and the drop-down interaction are covered by tests but not by eye.
π€ Generated with Claude Code